<!DOCTYPE html>
    <html>
    <head>
        <meta charset="UTF-8">
        <title>Spring Boot</title>
        <style>
</style>
        <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/katex@0.10.2/dist/katex.min.css" integrity="sha384-yFRtMMDnQtDRO8rLpMIKrtPCD5jdktao2TV19YiZYWMDkUR5GQZR/NOVTdquEx1j" crossorigin="anonymous">
<link href="https://cdn.jsdelivr.net/npm/katex-copytex@latest/dist/katex-copytex.min.css" rel="stylesheet" type="text/css">
        <link rel="stylesheet" href="https://cdn.jsdelivr.net/gh/Microsoft/vscode/extensions/markdown-language-features/media/markdown.css">
<link rel="stylesheet" href="https://cdn.jsdelivr.net/gh/Microsoft/vscode/extensions/markdown-language-features/media/highlight.css">
<style>
            body {
                font-family: -apple-system, BlinkMacSystemFont, 'Segoe WPC', 'Segoe UI', system-ui, 'Ubuntu', 'Droid Sans', sans-serif;
                font-size: 14px;
                line-height: 1.6;
            }
        </style>
        <style>
.task-list-item { list-style-type: none; } .task-list-item-checkbox { margin-left: -20px; vertical-align: middle; }
</style>
        
        <script src="https://cdn.jsdelivr.net/npm/katex-copytex@latest/dist/katex-copytex.min.js"></script>
        
    </head>
    <body class="vscode-light">
        <h1 id="spring-boot">Spring Boot</h1>
<h2 id="微服务的介绍">微服务的介绍</h2>
<p>将单体应用划分为小型的服务单元，服务单元之间使用网络的API进行资源访问与操作。</p>
<h2 id="微服务的优势">微服务的优势</h2>
<ol>
<li>服务的独立部署</li>
<li>服务的快速启动</li>
<li>更加合适的敏捷开发</li>
<li>职责专一</li>
<li>服务可动态按需扩容</li>
<li>代码的复用</li>
</ol>
<h2 id="什么是springboot">什么是SpringBoot</h2>
<ol>
<li>Spring开源项目下的子项目，是Spring组件一站式解决方案，简化使用spring的难度，减省了繁琐的配置，提供了各种启动器，开发者能快速上手。</li>
<li>约定大于配置</li>
</ol>
<h2 id="springboot的核心注解是哪个他是由哪几个注解组成">SpringBoot的核心注解是哪个？他是由哪几个注解组成?</h2>
<p>启动类上的注解@SpringBootApplication，Spring Boot的核心注解，主要组合包含以下三个注解：</p>
<ul>
<li>@SpringBootConfiguration: 组合了@Configuration注解，实现配置文件的功能。</li>
<li>@EnableAutoConfiguration：打开自动配置的功能，也可以关闭自动配置功能：@SpringBootApplication(excude= {DataSourceAutoConfiguration.class})</li>
<li>ComponentScan: Spring组件扫描。</li>
</ul>
<h2 id="什么是javaconfig">什么是JavaConfig？</h2>
<p>Spring JavaConfig是Spring社区的产品，它提供了配置Spring IoC容器的纯java方法。因此它有助于避免使用xml配置。JavaConfig的优点在于：</p>
<ol>
<li>面向对象的配置。</li>
<li>减少或消除xml配置。</li>
<li>类型安全和重构友好。</li>
</ol>
<h2 id="spring-boot自动配置原理是什么">Spring Boot自动配置原理是什么？</h2>
<ol>
<li>注解@EnableAutoConfigutation，@Configuration,@ConditionnalOnClass就是自动配置的核心</li>
<li>@EnableAutoConfiguration给容器导入META-INF/spring.factories里定义的自动配置类</li>
</ol>
<h2 id="如何理解springboot配置加载顺序">如何理解SpringBoot配置加载顺序？</h2>
<p>在Spring Boot里，可以使用以下方式来加载配置。</p>
<ol>
<li>properties文件</li>
<li>yaml文件</li>
<li>系统环境变量</li>
<li>命令行参数</li>
</ol>
<h2 id="什么是yaml">什么是yaml</h2>
<p>yaml是一种人类刻度的数据序列化语言。它通常用于配置文件。与属性文件相比，如果我们想要在配置文件中添加复杂的属性，<strong>yaml文件就更加结构化</strong>，而且更少混淆。</p>
<h2 id="yaml配置的优势在哪">yaml配置的优势在哪？</h2>
<ol>
<li>配置有序，在一些特殊的场景下，配置有序很关键。</li>
<li>支持数组，数组中的元素可以是基本数据类型也可以是对象</li>
<li>简介</li>
</ol>
<p>SpringBoot中使用Servlet监听器：</p>
<pre><code class="language-java"><div><span class="hljs-meta">@WebListener</span><span class="hljs-comment">//标识这是servelt的监听器</span>
<span class="hljs-keyword">public</span> <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">MyListener</span> <span class="hljs-keyword">implements</span> <span class="hljs-title">ServletContextListener</span> </span>{
    <span class="hljs-meta">@Override</span>
    <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title">contextInitialized</span><span class="hljs-params">(ServletContextEvent servletContextEvent)</span> </span>{
        System.out.println(<span class="hljs-string">"web==================="</span>);
    }

    <span class="hljs-meta">@Override</span>
    <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title">contextDestroyed</span><span class="hljs-params">(ServletContextEvent servletContextEvent)</span> </span>{
        System.out.println(<span class="hljs-string">"web down================"</span>);
    }
}

<span class="hljs-comment">// 启动类上, 在cn.viwiv包下</span>
<span class="hljs-meta">@SpringBootApplication</span>
<span class="hljs-keyword">public</span> <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">Application</span> </span>{
    <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">static</span> <span class="hljs-keyword">void</span> <span class="hljs-title">main</span><span class="hljs-params">(String[] args)</span> </span>{
        SpringApplication.run(Application.class,args);
    }

}
</div></code></pre>
<h2 id="spring的监听器">Spring的监听器</h2>
<p>Servlet监听器先于Spring的监听器启动。</p>
<pre><code class="language-java"><div><span class="hljs-comment">// ApplicationFailedEvent：该事件为spring boot启动失败时的操作</span>
<span class="hljs-comment">// ApplicationPreparedEvent：上下文context准备时触发</span>
<span class="hljs-comment">// ApplicationReadyEvent：上下文已经准备完毕的时候触发</span>
<span class="hljs-comment">// ApplicationStartedEvent：spring boot 启动监听类</span>
<span class="hljs-comment">// SpringApplicationEvent：获取SpringApplication</span>

ApplicationEnvironmentPreparedEvent：环境事先准备
<span class="hljs-meta">@Component</span>
<span class="hljs-keyword">public</span> <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">SpringSelfListener</span> <span class="hljs-keyword">implements</span> <span class="hljs-title">ApplicationListener</span>&lt;<span class="hljs-title">ApplicationEvent</span>&gt; </span>{
    <span class="hljs-meta">@Override</span>
    <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title">onApplicationEvent</span><span class="hljs-params">(ApplicationEvent ApplicationEvent)</span> </span>{
        System.out.println(<span class="hljs-string">"spring监听本身事件========="</span>+ApplicationEvent);
    }
}

<span class="hljs-comment">// 启动类</span>
<span class="hljs-meta">@SpringBootApplication</span>
<span class="hljs-meta">@ServletComponentScan</span>(<span class="hljs-string">"com.hzt"</span>)<span class="hljs-comment">//servlet监听器的使用</span>
<span class="hljs-keyword">public</span> <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">Application</span> </span>{
    <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">static</span> <span class="hljs-keyword">void</span> <span class="hljs-title">main</span><span class="hljs-params">(String[] args)</span> </span>{
        SpringApplication.run(Application.class,args);
    }

}
</div></code></pre>
<h2 id="读取配置文件">读取配置文件</h2>
<h4 id="1environment">1）Environment</h4>
<pre><code class="language-java"><div><span class="hljs-meta">@RestController</span>
<span class="hljs-keyword">public</span> <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">HelloController</span> </span>{

    <span class="hljs-comment">// 注入对象</span>
    <span class="hljs-meta">@Autowired</span>
    <span class="hljs-keyword">private</span> Environment env;

    <span class="hljs-meta">@GetMapping</span>(<span class="hljs-string">"/hello"</span>)
    <span class="hljs-function"><span class="hljs-keyword">public</span> String <span class="hljs-title">hello</span><span class="hljs-params">()</span> </span>{
        <span class="hljs-comment">// 读取配置</span>
        String port = env.getProperty(<span class="hljs-string">"server.port"</span>);
        <span class="hljs-keyword">return</span> port;
    }
}
</div></code></pre>
<h4 id="2value">2）@Value</h4>
<pre><code class="language-java"><div><span class="hljs-meta">@RestController</span>
<span class="hljs-keyword">public</span> <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">HelloController</span> </span>{

    <span class="hljs-comment">// 注入配置</span>
    <span class="hljs-meta">@Value</span>(<span class="hljs-string">"${server.port}"</span>)
    <span class="hljs-keyword">private</span> String port;

    <span class="hljs-meta">@GetMapping</span>(<span class="hljs-string">"/hello"</span>)
    <span class="hljs-function"><span class="hljs-keyword">public</span> String <span class="hljs-title">hello</span><span class="hljs-params">()</span> </span>{
        <span class="hljs-keyword">return</span> port;
    }
}
</div></code></pre>
<h4 id="3自定义配置类">3）自定义配置类</h4>
<pre><code class="language-java"><div><span class="hljs-meta">@ConfigurationProperties</span>(prefix = <span class="hljs-string">"net.biancheng"</span>)
<span class="hljs-meta">@Component</span>
<span class="hljs-keyword">public</span> <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">MyConfig</span> </span>{

    <span class="hljs-keyword">private</span> String name;

    <span class="hljs-function"><span class="hljs-keyword">public</span> String <span class="hljs-title">getName</span><span class="hljs-params">()</span> </span>{
        <span class="hljs-keyword">return</span> name;
    }

    <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title">setName</span><span class="hljs-params">(String name)</span> </span>{
        <span class="hljs-keyword">this</span>.name = name;
    }

}
</div></code></pre>
<pre><code class="language-java"><div><span class="hljs-meta">@RestController</span>
<span class="hljs-keyword">public</span> <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">HelloController</span> </span>{

    <span class="hljs-meta">@Autowired</span>
    <span class="hljs-keyword">private</span> MyConfig myConfig;

    <span class="hljs-meta">@GetMapping</span>(<span class="hljs-string">"/hello"</span>)
    <span class="hljs-function"><span class="hljs-keyword">public</span> String <span class="hljs-title">hello</span><span class="hljs-params">()</span> </span>{
        <span class="hljs-keyword">return</span> myConfig.getName();
    }
}
</div></code></pre>
<p>定义配置 application.properties 的方法如下：</p>
<p>net.biancheng.name=zhangsan</p>
<h1 id="actuator-监控">actuator 监控</h1>
<p>在生产环境中，需要实时或定期监控服务的可用性。</p>
<p>Spring Boot的actuator（健康监控）功能提供了很多监控所需的接口，可以对应用系统进行配置查看、相关功能统计等。</p>
<p>监控和管理自身应用信息的模块,spring-boot-starter-actuator</p>
<pre><code class="language-xml"><div><span class="hljs-tag">&lt;<span class="hljs-name">dependency</span>&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">groupId</span>&gt;</span>org.springframework.boot<span class="hljs-tag">&lt;/<span class="hljs-name">groupId</span>&gt;</span>
	<span class="hljs-tag">&lt;<span class="hljs-name">artifactId</span>&gt;</span>spring-boot-starter-actuator<span class="hljs-tag">&lt;/<span class="hljs-name">artifactId</span>&gt;</span>
<span class="hljs-tag">&lt;/<span class="hljs-name">dependency</span>&gt;</span>
</div></code></pre>
<p>如果使用HTTP调用的方式，还需要这个依赖：</p>
<pre><code class="language-xml"><div><span class="hljs-tag">&lt;<span class="hljs-name">dependency</span>&gt;</span>  
    <span class="hljs-tag">&lt;<span class="hljs-name">groupId</span>&gt;</span>org.springframework.boot<span class="hljs-tag">&lt;/<span class="hljs-name">groupId</span>&gt;</span>  
    <span class="hljs-tag">&lt;<span class="hljs-name">artifactId</span>&gt;</span>spring-boot-starter-web<span class="hljs-tag">&lt;/<span class="hljs-name">artifactId</span>&gt;</span>  
<span class="hljs-tag">&lt;/<span class="hljs-name">dependency</span>&gt;</span>  
</div></code></pre>
<p>application.yml中指定监控的HTTP端口（<strong>如果不指定，则使用和Server相同的端口</strong>）；指定去掉某项的检查（比如不监控health.mail）:</p>
<pre><code class="language-yml"><div>
<span class="hljs-attr">server:</span>  
<span class="hljs-attr">  port:</span> <span class="hljs-number">8082</span>   <span class="hljs-comment"># http的端口</span>
<span class="hljs-attr">management:</span>  
<span class="hljs-attr">  server:</span>
<span class="hljs-attr">    port:</span> <span class="hljs-number">54001</span>
<span class="hljs-attr">  health:</span>  
<span class="hljs-attr">    mail:</span>  
<span class="hljs-attr">      enabled:</span> <span class="hljs-literal">false</span>  
<span class="hljs-attr">  endpoint:</span> 
<span class="hljs-attr">    beans:</span>
<span class="hljs-attr">      enabled:</span> <span class="hljs-literal">true</span> <span class="hljs-comment"># 开启bean</span>
<span class="hljs-attr">    health:</span>
<span class="hljs-attr">      show-details:</span> <span class="hljs-string">always</span> <span class="hljs-comment"># health 显示细节</span>
</div></code></pre>
<p>比如，我们访问 /actuator/health 可以得到下面的信息：</p>
<pre><code class="language-json"><div>{
  <span class="hljs-attr">"status"</span>: <span class="hljs-string">"UP"</span>
}
</div></code></pre>
<table>
<thead>
<tr>
<th>Http方法</th>
<th>路径</th>
<th>描述</th>
<th>Http默认暴露</th>
</tr>
</thead>
<tbody>
<tr>
<td>GET</td>
<td>/actuator/conflgprops</td>
<td>查看配置属性，包含默认配置</td>
<td>false</td>
</tr>
<tr>
<td>GET</td>
<td>/actuator/beans</td>
<td>查看bean及其关系列表</td>
<td>false</td>
</tr>
<tr>
<td>GET</td>
<td>/actuator/heapdump</td>
<td>打印线程栈</td>
<td>false</td>
</tr>
<tr>
<td>GET</td>
<td>/actuator/env</td>
<td>查看所有环境变量</td>
<td>false</td>
</tr>
<tr>
<td>GET</td>
<td>/actuator/env/ {name}</td>
<td>查看具体变量值</td>
<td>true</td>
</tr>
<tr>
<td>GET</td>
<td>/actuator/health</td>
<td>查看应用健康指标</td>
<td>true</td>
</tr>
<tr>
<td>GET</td>
<td>/actuator/info</td>
<td>查看应用信息</td>
<td>false</td>
</tr>
<tr>
<td>GET</td>
<td>/actuator/mappings</td>
<td>查看所有 URL 映射</td>
<td>false</td>
</tr>
<tr>
<td>GET</td>
<td>/actuator/metrics</td>
<td>查看应用基本指标</td>
<td>false</td>
</tr>
<tr>
<td>GET</td>
<td>/actuator/metrics/{name}</td>
<td>查看具体指标</td>
<td>false</td>
</tr>
<tr>
<td>POST</td>
<td>/actuator/shutdown</td>
<td>关闭应用</td>
<td>false</td>
</tr>
<tr>
<td>GET</td>
<td>/actuator/httptrace</td>
<td>查看基本追踪信息</td>
<td>false</td>
</tr>
<tr>
<td>GET</td>
<td>/actuator/loggers</td>
<td>显示应用程序中 loggers 配置</td>
<td>false</td>
</tr>
<tr>
<td>GET</td>
<td>/actuator/scheduledtasks</td>
<td>显示定时任务</td>
<td>false</td>
</tr>
</tbody>
</table>
<p>UP 表示当前应用处于健康状态，如果是 DOWN 就表示当前应用不健康。增加下面的配置可以让一些健康信息的详情也显示出来：</p>
<pre><code class="language-properties"><div><span class="hljs-meta">management.endpoint.health.show-details</span>=<span class="hljs-string">ALWAYS</span>
</div></code></pre>
<p>再次访问 /actuator/health，就可以得到健康状态的详细信息：</p>
<pre><code class="language-json"><div>{
  <span class="hljs-attr">"status"</span>: <span class="hljs-string">"UP"</span>,
  <span class="hljs-attr">"diskSpace"</span>: {
    <span class="hljs-attr">"status"</span>: <span class="hljs-string">"UP"</span>,
    <span class="hljs-attr">"total"</span>: <span class="hljs-number">491270434816</span>,
    <span class="hljs-attr">"free"</span>: <span class="hljs-number">383870214144</span>,
    <span class="hljs-attr">"threshold"</span>: <span class="hljs-number">10485760</span>
  }
}
</div></code></pre>
<p>大部分端点默认都不暴露出来，我们可以手动配置需要暴露的端点。如果需要暴露多个端点，可以用逗号分隔，如下所示：</p>
<pre><code class="language-properties"><div><span class="hljs-meta">management.endpoints.web.exposure.include</span>=<span class="hljs-string">configprops,beans</span>
</div></code></pre>
<p>如果想全部端点都暴露的话直接配置成下面的方式：</p>
<pre><code class="language-properties"><div><span class="hljs-meta">management.endpoints.web.exposure.include</span>=<span class="hljs-string">*</span>
</div></code></pre>
<h3 id="info-信息配置">info 信息配置</h3>
<pre><code class="language-yml"><div><span class="hljs-attr">info:</span>
<span class="hljs-attr">  app:</span> <span class="hljs-string">${spring.application.name}</span> <span class="hljs-comment"># yaml中的配置</span>
<span class="hljs-attr">  build:</span>
  	<span class="hljs-attr">artifactId:</span> <span class="hljs-string">${project.artifactId}</span> <span class="hljs-comment"># 读取pom.xml中的版本，前提是配置maven插件 maven-resources-plugin</span>
<span class="hljs-attr">    version:</span> <span class="hljs-string">${project.version}</span> <span class="hljs-comment"># 读取pom.xml中的版本，前提是配置maven插件 maven-resources-plugin</span>
</div></code></pre>
<pre><code class="language-xml"><div><span class="hljs-tag">&lt;<span class="hljs-name">build</span>&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">resources</span>&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">resource</span>&gt;</span>
            <span class="hljs-tag">&lt;<span class="hljs-name">directory</span>&gt;</span>src/main/resources<span class="hljs-tag">&lt;/<span class="hljs-name">directory</span>&gt;</span>
            <span class="hljs-tag">&lt;<span class="hljs-name">filtering</span>&gt;</span>true<span class="hljs-tag">&lt;/<span class="hljs-name">filtering</span>&gt;</span>
        <span class="hljs-tag">&lt;/<span class="hljs-name">resource</span>&gt;</span>
    <span class="hljs-tag">&lt;/<span class="hljs-name">resources</span>&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">plugins</span>&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">plugin</span>&gt;</span>
          <span class="hljs-tag">&lt;<span class="hljs-name">groupId</span>&gt;</span>org.apache.maven.plugins<span class="hljs-tag">&lt;/<span class="hljs-name">groupId</span>&gt;</span>
          <span class="hljs-tag">&lt;<span class="hljs-name">artifactId</span>&gt;</span>maven-resources-plugin<span class="hljs-tag">&lt;/<span class="hljs-name">artifactId</span>&gt;</span>
          <span class="hljs-tag">&lt;<span class="hljs-name">configuration</span>&gt;</span>
              <span class="hljs-tag">&lt;<span class="hljs-name">delimiters</span>&gt;</span>
                  <span class="hljs-tag">&lt;<span class="hljs-name">delimit</span>&gt;</span>${*}<span class="hljs-tag">&lt;/<span class="hljs-name">delimit</span>&gt;</span><span class="hljs-comment">&lt;!-- *代表内容 --&gt;</span>
              <span class="hljs-tag">&lt;/<span class="hljs-name">delimiters</span>&gt;</span>
          <span class="hljs-tag">&lt;/<span class="hljs-name">configuration</span>&gt;</span>
      <span class="hljs-tag">&lt;/<span class="hljs-name">plugin</span>&gt;</span>
    <span class="hljs-tag">&lt;/<span class="hljs-name">plugins</span>&gt;</span>
<span class="hljs-tag">&lt;/<span class="hljs-name">build</span>&gt;</span>
</div></code></pre>
<h2 id="自定义-actuator-端点">自定义 actuator 端点</h2>
<h1 id="spring-boot-创建starter">Spring Boot 创建Starter</h1>
<p>创建一个项目 spring-boot-starter-demo。</p>
<p>如果一个配置类只配置@ConfigurationProperties注解，而没有使用@Component，那么在IOC容器中是获取不到properties 配置文件转化的bean。</p>
<pre><code class="language-java"><div><span class="hljs-comment">// spring.user对应的值映射到UserPorperties类上， 创建创建类但是没有生成bean，可以使用@Component生成bean</span>
<span class="hljs-meta">@ConfigurationProperties</span>(<span class="hljs-string">"spring.user"</span>)
<span class="hljs-keyword">public</span> <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">UserPorperties</span> </span>{
    <span class="hljs-keyword">private</span> String name;
    <span class="hljs-comment">// 实现get,set方法</span>
}
</div></code></pre>
<pre><code class="language-java"><div><span class="hljs-keyword">public</span> <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">UserClient</span> </span>{
    <span class="hljs-keyword">private</span> UserPorperties userPorperties;
    <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-title">UserClient</span><span class="hljs-params">()</span> </span>{
    }
    <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-title">UserClient</span><span class="hljs-params">(UserPorperties p)</span> </span>{
        <span class="hljs-keyword">this</span>.userPorperties = p;
    }
    <span class="hljs-function"><span class="hljs-keyword">public</span> String <span class="hljs-title">getName</span><span class="hljs-params">()</span> </span>{
        <span class="hljs-keyword">return</span> userPorperties.getName();
    }
}
</div></code></pre>
<pre><code class="language-java"><div><span class="hljs-meta">@Configuration</span>
<span class="hljs-meta">@EnableConfigurationProperties</span>(UserPorperties.class)
<span class="hljs-keyword">public</span> <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">UserAutoConfigure</span> </span>{

    <span class="hljs-meta">@Bean</span>
    <span class="hljs-meta">@ConditionalOnProperty</span>(prefix = <span class="hljs-string">"spring.user"</span>, value = <span class="hljs-string">"enabled"</span>, havingValue = <span class="hljs-string">"true"</span>) <span class="hljs-comment">// 条件满足生成bean</span>
    <span class="hljs-function"><span class="hljs-keyword">public</span> UserClient <span class="hljs-title">userClient</span><span class="hljs-params">(UserPorperties userPorperties)</span> </span>{
        <span class="hljs-keyword">return</span> <span class="hljs-keyword">new</span> UserClient(userPorperties);
    }
}
</div></code></pre>
<h2 id="小插入生成bean的方式">小插入：生成bean的方式</h2>
<h3 id="方式1配置文件">方式1：配置文件</h3>
<pre><code class="language-xml"><div><span class="hljs-tag">&lt;<span class="hljs-name">bean</span> <span class="hljs-attr">id</span>=<span class="hljs-string">"xxxx"</span>  <span class="hljs-attr">class</span>=<span class="hljs-string">"xxxx.xxxx"</span>/&gt;</span>
</div></code></pre>
<h3 id="方式2componentservicecontrolerrepository">方式2：@Component,@Service,@Controler,@Repository（</h3>
<p>特定功能的注解， 底层是@Component）都是单例</p>
<p>如果被注解的类不在SpringBoot的启动类的根目录及其子目录下，需要使用扫描来生成bean</p>
<pre><code class="language-java"><div><span class="hljs-meta">@ComponentScan</span>(value={<span class="hljs-string">"扫描的包"</span>,<span class="hljs-string">"扫描的包"</span>})
</div></code></pre>
<h3 id="方式3使用bean注解这种方式用在spring-boot-应用中">方式3：使用@Bean注解,这种方式用在<strong>Spring Boot 应用</strong>中。</h3>
<p>bean的默认名是类的首字母小写，可以使用@Bean(&quot;xxx&quot;)定义bean名</p>
<p>配合@Configuration使用</p>
<p>@Configuration 标识这是一个Spring Boot 配置类，其将会扫描该类中是否存在@Bean 注解的方法</p>
<p>也会存<strong>在扫描路径的问题</strong>，除了以上的解决方式，还有使用Spring boot starter 的解决方式</p>
<p>在resources下创建如下文件。META-INF/spring.factories.</p>
<p>添加如下代码：</p>
<pre><code class="language-factories"><code><div>org.springframework.boot.autoconfigure.EnableAutoConfiguration=Configuration全限定类名
</div></code></code></pre>
<p>如果不成功，引入如下依赖：</p>
<pre><code class="language-xml"><div><span class="hljs-tag">&lt;<span class="hljs-name">dependency</span>&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">groupId</span>&gt;</span>org.springframework.boot<span class="hljs-tag">&lt;/<span class="hljs-name">groupId</span>&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">artifactId</span>&gt;</span>spring-boot-configuration-processor<span class="hljs-tag">&lt;/<span class="hljs-name">artifactId</span>&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">optional</span>&gt;</span>true<span class="hljs-tag">&lt;/<span class="hljs-name">optional</span>&gt;</span>
<span class="hljs-tag">&lt;/<span class="hljs-name">dependency</span>&gt;</span>  
</div></code></pre>
<h3 id="方式4使用注解import">方式4：使用注解@Import</h3>
<pre><code class="language-java"><div><span class="hljs-meta">@Import</span>(User.class)
<span class="hljs-keyword">public</span> <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">MicroblogUserWebApplication</span> </span>{
    <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">static</span> <span class="hljs-keyword">void</span> <span class="hljs-title">main</span><span class="hljs-params">(String args[])</span> </span>{
        SpringApplication.run(MicroblogUserWebApplication.class, args);
    }
}
</div></code></pre>
<h3 id="引入stater">引入stater</h3>
<pre><code class="language-xml"><div><span class="hljs-tag">&lt;<span class="hljs-name">dependency</span>&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">groupId</span>&gt;</span>xxxxx.xxxx<span class="hljs-tag">&lt;/<span class="hljs-name">groupId</span>&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">artifactId</span>&gt;</span>spring-boot-starter-demo<span class="hljs-tag">&lt;/<span class="hljs-name">artifactId</span>&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">version</span>&gt;</span>版本号<span class="hljs-tag">&lt;/<span class="hljs-name">version</span>&gt;</span>
<span class="hljs-tag">&lt;/<span class="hljs-name">dependency</span>&gt;</span>
</div></code></pre>
<h3 id="使用时直接注入">使用时直接注入</h3>
<pre><code class="language-java"><div><span class="hljs-meta">@RestController</span>
<span class="hljs-keyword">public</span> <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">UserController</span> </span>{
    <span class="hljs-meta">@Autowired</span>
    <span class="hljs-keyword">private</span> UserClient userClient;
    <span class="hljs-meta">@GetMapping</span>(<span class="hljs-string">"/user/name"</span>)
    <span class="hljs-function"><span class="hljs-keyword">public</span> String <span class="hljs-title">getUserName</span><span class="hljs-params">()</span> </span>{
        <span class="hljs-keyword">return</span> userClient.getName();
    }
}
</div></code></pre>
<p>属性文件中配置 name 的值和开启 UserClient：</p>
<pre><code class="language-yml"><div><span class="hljs-attr">spring:</span>
	<span class="hljs-attr">user:</span>
		<span class="hljs-attr">name:</span> <span class="hljs-string">zhangsan</span>
		<span class="hljs-attr">enabled:</span> <span class="hljs-literal">true</span>
</div></code></pre>
<p>访问 /user/name 就可以返回我们配置的 zhangsan。</p>
<h1 id="spring-boot和spring-cloud">Spring Boot和Spring Cloud</h1>
<p>The easiest way to get started is visit(访问) <a href="https://start.spring.io/">start.spring.io</a>, select your Spring Boot version and the Spring Cloud projects you want to use. This will add the corresponding(相应的) Spring Cloud BOM version to your Maven/Gradle file when you generate the project.</p>
<p>官网：<a href="https://spring.io/projects/spring-cloud">https://spring.io/projects/spring-cloud</a></p>
<p>查看对应的文档对象模型版本：</p>
<p><img src="file:///e:\notepad\notepad\springboot\spring%E5%9F%BA%E7%A1%80\assets\image-20201215141346880.png" alt="image-20201215141346880"></p>
<p>版本查看：<a href="https://start.spring.io/actuator/info">https://start.spring.io/actuator/info</a></p>
<p><img src="file:///e:\notepad\notepad\springboot\spring%E5%9F%BA%E7%A1%80\assets\image-20201215145546186.png" alt="image-20201215145546186"></p>
<p><img src="file:///e:\notepad\notepad\springboot\spring%E5%9F%BA%E7%A1%80\assets\image-20201215145616658.png" alt="image-20201215145616658"></p>
<p>Spring Cloud Dalston, Edgware, and Finchley have all reached end of life status(达到报废状态) and are no longer supported.(不再被支持)</p>
<p>Bug fixes and backwards compatible features(向下兼容性) are added to each release(版本) train via(经由，通过) a service release (SR， 服务版本).</p>
<p>Once you determine which version of Spring Cloud to use, you should use the latest service release for that release train.（一旦确定要使用哪个版本的Spring Cloud，就应该使用该版本系列的最新服务版本<code>&lt;Spring Cloud的版本</code>&gt;。）</p>
<pre><code class="language-xml"><div><span class="hljs-tag">&lt;<span class="hljs-name">properties</span>&gt;</span>
    <span class="hljs-comment">&lt;!--自己Spring Boot对应的版本 --&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">spring.cloud-version</span>&gt;</span>Hoxton.SR8<span class="hljs-tag">&lt;/<span class="hljs-name">spring.cloud-version</span>&gt;</span>
<span class="hljs-tag">&lt;/<span class="hljs-name">properties</span>&gt;</span>
<span class="hljs-tag">&lt;<span class="hljs-name">dependencyManagement</span>&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">dependencies</span>&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">dependency</span>&gt;</span>
            <span class="hljs-tag">&lt;<span class="hljs-name">groupId</span>&gt;</span>org.springframework.cloud<span class="hljs-tag">&lt;/<span class="hljs-name">groupId</span>&gt;</span>
            <span class="hljs-tag">&lt;<span class="hljs-name">artifactId</span>&gt;</span>spring-cloud-dependencies<span class="hljs-tag">&lt;/<span class="hljs-name">artifactId</span>&gt;</span>
            <span class="hljs-tag">&lt;<span class="hljs-name">version</span>&gt;</span>${spring.cloud-version}<span class="hljs-tag">&lt;/<span class="hljs-name">version</span>&gt;</span>
            <span class="hljs-tag">&lt;<span class="hljs-name">type</span>&gt;</span>pom<span class="hljs-tag">&lt;/<span class="hljs-name">type</span>&gt;</span>
            <span class="hljs-tag">&lt;<span class="hljs-name">scope</span>&gt;</span>import<span class="hljs-tag">&lt;/<span class="hljs-name">scope</span>&gt;</span>
        <span class="hljs-tag">&lt;/<span class="hljs-name">dependency</span>&gt;</span>
    <span class="hljs-tag">&lt;/<span class="hljs-name">dependencies</span>&gt;</span>
<span class="hljs-tag">&lt;/<span class="hljs-name">dependencyManagement</span>&gt;</span>
</div></code></pre>
<p>SpringCloud2020:</p>
<p><img src="file:///e:\notepad\notepad\springboot\spring%E5%9F%BA%E7%A1%80\assets\image-20210115112455464.png" alt="image-20210115112455464"></p>
<p><img src="file:///e:\notepad\notepad\springboot\spring%E5%9F%BA%E7%A1%80\assets\image-20201215151551803.png" alt="image-20201215151551803"></p>
<p>spring-alibaba：<a href="https://spring-cloud-alibaba-group.github.io/github-pages/hoxton/zh-cn/index.html">https://spring-cloud-alibaba-group.github.io/github-pages/hoxton/zh-cn/index.html</a></p>
<p>版本选择：<a href="https://github.com/alibaba/spring-cloud-alibaba/wiki/%E7%89%88%E6%9C%AC%E8%AF%B4%E6%98%8E">https://github.com/alibaba/spring-cloud-alibaba/wiki/版本说明</a></p>
<p><img src="file:///e:\notepad\notepad\springboot\spring%E5%9F%BA%E7%A1%80\assets\image-20201217101614494.png" alt="image-20201217101614494"></p>
<h2 id="以订单-支付模块为例">以订单-支付模块为例</h2>
<p>建立一个公共模块放所有的实体类</p>
<h3 id="更改maven">更改maven</h3>
<pre><code class="language-xml"><div><span class="hljs-meta">&lt;?xml version="1.0" encoding="UTF-8"?&gt;</span>

<span class="hljs-tag">&lt;<span class="hljs-name">project</span> <span class="hljs-attr">xmlns</span>=<span class="hljs-string">"http://maven.apache.org/POM/4.0.0"</span> <span class="hljs-attr">xmlns:xsi</span>=<span class="hljs-string">"http://www.w3.org/2001/XMLSchema-instance"</span>
  <span class="hljs-attr">xsi:schemaLocation</span>=<span class="hljs-string">"http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"</span>&gt;</span>
  <span class="hljs-tag">&lt;<span class="hljs-name">modelVersion</span>&gt;</span>4.0.0<span class="hljs-tag">&lt;/<span class="hljs-name">modelVersion</span>&gt;</span>
  <span class="hljs-tag">&lt;<span class="hljs-name">groupId</span>&gt;</span>cn.team102<span class="hljs-tag">&lt;/<span class="hljs-name">groupId</span>&gt;</span>
  <span class="hljs-tag">&lt;<span class="hljs-name">artifactId</span>&gt;</span>SpringCloud<span class="hljs-tag">&lt;/<span class="hljs-name">artifactId</span>&gt;</span>
  <span class="hljs-tag">&lt;<span class="hljs-name">version</span>&gt;</span>1.0-SNAPSHOT<span class="hljs-tag">&lt;/<span class="hljs-name">version</span>&gt;</span>
  <span class="hljs-tag">&lt;<span class="hljs-name">modules</span>&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">module</span>&gt;</span>payment<span class="hljs-tag">&lt;/<span class="hljs-name">module</span>&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">module</span>&gt;</span>commont<span class="hljs-tag">&lt;/<span class="hljs-name">module</span>&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">module</span>&gt;</span>order<span class="hljs-tag">&lt;/<span class="hljs-name">module</span>&gt;</span>
  <span class="hljs-tag">&lt;/<span class="hljs-name">modules</span>&gt;</span>
  <span class="hljs-tag">&lt;<span class="hljs-name">packaging</span>&gt;</span>pom<span class="hljs-tag">&lt;/<span class="hljs-name">packaging</span>&gt;</span>
  <span class="hljs-tag">&lt;<span class="hljs-name">name</span>&gt;</span>Maven<span class="hljs-tag">&lt;/<span class="hljs-name">name</span>&gt;</span>
  <span class="hljs-tag">&lt;<span class="hljs-name">properties</span>&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">project.build.sourceEncoding</span>&gt;</span>UTF-8<span class="hljs-tag">&lt;/<span class="hljs-name">project.build.sourceEncoding</span>&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">spring.boot.version</span>&gt;</span>2.3.5.RELEASE<span class="hljs-tag">&lt;/<span class="hljs-name">spring.boot.version</span>&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">spring.cloud.version</span>&gt;</span>Hoxton.SR8<span class="hljs-tag">&lt;/<span class="hljs-name">spring.cloud.version</span>&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">spring.cloud.alibaba.version</span>&gt;</span>2.2.3.RELEASE<span class="hljs-tag">&lt;/<span class="hljs-name">spring.cloud.alibaba.version</span>&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">mysql.jdbc.driver.version</span>&gt;</span>8.0.21<span class="hljs-tag">&lt;/<span class="hljs-name">mysql.jdbc.driver.version</span>&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">druid.version</span>&gt;</span>1.1.16<span class="hljs-tag">&lt;/<span class="hljs-name">druid.version</span>&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">log4j.version</span>&gt;</span>1.2.17<span class="hljs-tag">&lt;/<span class="hljs-name">log4j.version</span>&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">junit.version</span>&gt;</span>4.12<span class="hljs-tag">&lt;/<span class="hljs-name">junit.version</span>&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">lombok.version</span>&gt;</span>1.18.16<span class="hljs-tag">&lt;/<span class="hljs-name">lombok.version</span>&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">mybatis.spring.boot.version</span>&gt;</span>1.3.0<span class="hljs-tag">&lt;/<span class="hljs-name">mybatis.spring.boot.version</span>&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">druid.spring.boot.version</span>&gt;</span>1.1.10<span class="hljs-tag">&lt;/<span class="hljs-name">druid.spring.boot.version</span>&gt;</span>
  <span class="hljs-tag">&lt;/<span class="hljs-name">properties</span>&gt;</span>
  <span class="hljs-comment">&lt;!-- 子模块继承后，提供锁定版本+子模块不用写groupId和version--&gt;</span>
  <span class="hljs-tag">&lt;<span class="hljs-name">dependencyManagement</span>&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">dependencies</span>&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">dependency</span>&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">groupId</span>&gt;</span>org.springframework.boot<span class="hljs-tag">&lt;/<span class="hljs-name">groupId</span>&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">artifactId</span>&gt;</span>spring-boot-dependencies<span class="hljs-tag">&lt;/<span class="hljs-name">artifactId</span>&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">version</span>&gt;</span>${spring.boot.version}<span class="hljs-tag">&lt;/<span class="hljs-name">version</span>&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">type</span>&gt;</span>pom<span class="hljs-tag">&lt;/<span class="hljs-name">type</span>&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">scope</span>&gt;</span>import<span class="hljs-tag">&lt;/<span class="hljs-name">scope</span>&gt;</span>
      <span class="hljs-tag">&lt;/<span class="hljs-name">dependency</span>&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">dependency</span>&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">groupId</span>&gt;</span>org.springframework.cloud<span class="hljs-tag">&lt;/<span class="hljs-name">groupId</span>&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">artifactId</span>&gt;</span>spring-cloud-dependencies<span class="hljs-tag">&lt;/<span class="hljs-name">artifactId</span>&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">version</span>&gt;</span>${spring.cloud.version}<span class="hljs-tag">&lt;/<span class="hljs-name">version</span>&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">type</span>&gt;</span>pom<span class="hljs-tag">&lt;/<span class="hljs-name">type</span>&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">scope</span>&gt;</span>import<span class="hljs-tag">&lt;/<span class="hljs-name">scope</span>&gt;</span>
      <span class="hljs-tag">&lt;/<span class="hljs-name">dependency</span>&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">dependency</span>&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">groupId</span>&gt;</span>com.alibaba.cloud<span class="hljs-tag">&lt;/<span class="hljs-name">groupId</span>&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">artifactId</span>&gt;</span>spring-cloud-alibaba-dependencies<span class="hljs-tag">&lt;/<span class="hljs-name">artifactId</span>&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">version</span>&gt;</span>${spring.cloud.alibaba.version}<span class="hljs-tag">&lt;/<span class="hljs-name">version</span>&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">type</span>&gt;</span>pom<span class="hljs-tag">&lt;/<span class="hljs-name">type</span>&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">scope</span>&gt;</span>import<span class="hljs-tag">&lt;/<span class="hljs-name">scope</span>&gt;</span>
      <span class="hljs-tag">&lt;/<span class="hljs-name">dependency</span>&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">dependency</span>&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">groupId</span>&gt;</span>com.alibaba<span class="hljs-tag">&lt;/<span class="hljs-name">groupId</span>&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">artifactId</span>&gt;</span>druid-spring-boot-starter<span class="hljs-tag">&lt;/<span class="hljs-name">artifactId</span>&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">version</span>&gt;</span>${druid.spring.boot.version}<span class="hljs-tag">&lt;/<span class="hljs-name">version</span>&gt;</span>
      <span class="hljs-tag">&lt;/<span class="hljs-name">dependency</span>&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">dependency</span>&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">groupId</span>&gt;</span>org.mybatis.spring.boot<span class="hljs-tag">&lt;/<span class="hljs-name">groupId</span>&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">artifactId</span>&gt;</span>mybatis-spring-boot-starter<span class="hljs-tag">&lt;/<span class="hljs-name">artifactId</span>&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">version</span>&gt;</span>${mybatis.spring.boot.version}<span class="hljs-tag">&lt;/<span class="hljs-name">version</span>&gt;</span>
      <span class="hljs-tag">&lt;/<span class="hljs-name">dependency</span>&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">dependency</span>&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">groupId</span>&gt;</span>mysql<span class="hljs-tag">&lt;/<span class="hljs-name">groupId</span>&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">artifactId</span>&gt;</span>mysql-connector-java<span class="hljs-tag">&lt;/<span class="hljs-name">artifactId</span>&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">version</span>&gt;</span>${mysql.jdbc.driver.version}<span class="hljs-tag">&lt;/<span class="hljs-name">version</span>&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">scope</span>&gt;</span>import<span class="hljs-tag">&lt;/<span class="hljs-name">scope</span>&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">type</span>&gt;</span>pom<span class="hljs-tag">&lt;/<span class="hljs-name">type</span>&gt;</span>
      <span class="hljs-tag">&lt;/<span class="hljs-name">dependency</span>&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">dependency</span>&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">groupId</span>&gt;</span>com.alibaba<span class="hljs-tag">&lt;/<span class="hljs-name">groupId</span>&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">artifactId</span>&gt;</span>druid<span class="hljs-tag">&lt;/<span class="hljs-name">artifactId</span>&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">version</span>&gt;</span>${druid.version}<span class="hljs-tag">&lt;/<span class="hljs-name">version</span>&gt;</span>
      <span class="hljs-tag">&lt;/<span class="hljs-name">dependency</span>&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">dependency</span>&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">groupId</span>&gt;</span>junit<span class="hljs-tag">&lt;/<span class="hljs-name">groupId</span>&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">artifactId</span>&gt;</span>junit<span class="hljs-tag">&lt;/<span class="hljs-name">artifactId</span>&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">version</span>&gt;</span>${junit.version}<span class="hljs-tag">&lt;/<span class="hljs-name">version</span>&gt;</span>
      <span class="hljs-tag">&lt;/<span class="hljs-name">dependency</span>&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">dependency</span>&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">groupId</span>&gt;</span>org.projectlombok<span class="hljs-tag">&lt;/<span class="hljs-name">groupId</span>&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">artifactId</span>&gt;</span>lombok<span class="hljs-tag">&lt;/<span class="hljs-name">artifactId</span>&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">version</span>&gt;</span>${lombok.version}<span class="hljs-tag">&lt;/<span class="hljs-name">version</span>&gt;</span>
      <span class="hljs-tag">&lt;/<span class="hljs-name">dependency</span>&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">dependency</span>&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">groupId</span>&gt;</span>log4j<span class="hljs-tag">&lt;/<span class="hljs-name">groupId</span>&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">artifactId</span>&gt;</span>log4j<span class="hljs-tag">&lt;/<span class="hljs-name">artifactId</span>&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">version</span>&gt;</span>${log4j.version}<span class="hljs-tag">&lt;/<span class="hljs-name">version</span>&gt;</span>
      <span class="hljs-tag">&lt;/<span class="hljs-name">dependency</span>&gt;</span>
    <span class="hljs-tag">&lt;/<span class="hljs-name">dependencies</span>&gt;</span>
  <span class="hljs-tag">&lt;/<span class="hljs-name">dependencyManagement</span>&gt;</span>
  <span class="hljs-tag">&lt;<span class="hljs-name">build</span>&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">plugins</span>&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">plugin</span>&gt;</span>
          <span class="hljs-tag">&lt;<span class="hljs-name">groupId</span>&gt;</span>org.springframework.boot<span class="hljs-tag">&lt;/<span class="hljs-name">groupId</span>&gt;</span>
          <span class="hljs-tag">&lt;<span class="hljs-name">artifactId</span>&gt;</span>spring-boot-maven-plugin<span class="hljs-tag">&lt;/<span class="hljs-name">artifactId</span>&gt;</span>
          <span class="hljs-tag">&lt;<span class="hljs-name">version</span>&gt;</span>${spring.boot.version}<span class="hljs-tag">&lt;/<span class="hljs-name">version</span>&gt;</span>
          <span class="hljs-tag">&lt;<span class="hljs-name">configuration</span>&gt;</span>
            <span class="hljs-tag">&lt;<span class="hljs-name">fork</span>&gt;</span>true<span class="hljs-tag">&lt;/<span class="hljs-name">fork</span>&gt;</span>
            <span class="hljs-tag">&lt;<span class="hljs-name">addResources</span>&gt;</span>true<span class="hljs-tag">&lt;/<span class="hljs-name">addResources</span>&gt;</span>
          <span class="hljs-tag">&lt;/<span class="hljs-name">configuration</span>&gt;</span>
      <span class="hljs-tag">&lt;/<span class="hljs-name">plugin</span>&gt;</span>
    <span class="hljs-tag">&lt;/<span class="hljs-name">plugins</span>&gt;</span>
  <span class="hljs-tag">&lt;/<span class="hljs-name">build</span>&gt;</span>
<span class="hljs-tag">&lt;/<span class="hljs-name">project</span>&gt;</span>
</div></code></pre>
<h3 id="使用resttemplate">使用RestTemplate</h3>
<p>创建配置文件，实现bean</p>
<p>基本使用：</p>
<pre><code class="language-java"><div><span class="hljs-comment">// 方法参数看源码</span>
<span class="hljs-comment">// 得到http的全部信息，响应状态，响应头，响应体</span>
restTeamplate.postForEntity(url, xxx);
<span class="hljs-comment">// 不得到http请求的全部信息</span>
restTemplate.postForObject(url, 传递的参数, 封装到哪个公共类); 
restTemplate.getForObject(url, 传递的参数, 封装到哪个公共类);
</div></code></pre>
<h2 id="服务注册中心">服务注册中心</h2>
<p>什么是服务治理？</p>
<h3 id="eurekaap-可用容错">Eureka(AP, 可用、容错)</h3>
<p>Eureka 是一个基于 REST(Representational State Transfer, <em>表述性状态传递</em>)的服务,提供服务定位(locating services)、负载均衡(load balancing)、故障转移(failover of middle-tier servers),在 Spring Cloud 子项目 Spring Cloud Netflix 中。</p>
<p>spring-cloud-starter-netflix-eureka-xxx</p>
<p>包括server和client</p>
<pre><code class="language-xml"><div><span class="hljs-comment">&lt;!--根据版本引入依赖2018以后用下面依赖--&gt;</span>
<span class="hljs-comment">&lt;!-- 服务端 --&gt;</span>
<span class="hljs-tag">&lt;<span class="hljs-name">dependency</span>&gt;</span>
	<span class="hljs-tag">&lt;<span class="hljs-name">groupId</span>&gt;</span>org.springframework.cloud<span class="hljs-tag">&lt;/<span class="hljs-name">groupId</span>&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">artifactId</span>&gt;</span>spring-cloud-starter-netflix-eureka-server<span class="hljs-tag">&lt;/<span class="hljs-name">artifactId</span>&gt;</span>
<span class="hljs-tag">&lt;/<span class="hljs-name">dependency</span>&gt;</span>

<span class="hljs-comment">&lt;!-- 客户端 --&gt;</span>
<span class="hljs-tag">&lt;<span class="hljs-name">dependency</span>&gt;</span>
	<span class="hljs-tag">&lt;<span class="hljs-name">groupId</span>&gt;</span>org.springframework.cloud<span class="hljs-tag">&lt;/<span class="hljs-name">groupId</span>&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">artifactId</span>&gt;</span>spring-cloud-starter-netflix-eureka-client<span class="hljs-tag">&lt;/<span class="hljs-name">artifactId</span>&gt;</span>
<span class="hljs-tag">&lt;/<span class="hljs-name">dependency</span>&gt;</span>
</div></code></pre>
<p>编写server的yml</p>
<pre><code class="language-yml"><div><span class="hljs-attr">eureka:</span>
	<span class="hljs-attr">instance:</span>
		<span class="hljs-attr">hostname:</span> <span class="hljs-string">localhost</span> <span class="hljs-comment"># eureka服务端的实例名称</span>
	<span class="hljs-attr">client:</span> 
		<span class="hljs-comment"># false表示不向注册中心注册自己</span>
		<span class="hljs-attr">register-with-eureka:</span> <span class="hljs-literal">false</span>
		<span class="hljs-comment"># false表示自己就是注册中心，我的职责就是维护服务实例，并不需要检索服务</span>
		<span class="hljs-attr">fetch-registry:</span> <span class="hljs-literal">false</span>
		<span class="hljs-attr">service-url:</span>
			<span class="hljs-comment"># 设置与Eureka Server交互的地址查询服务和注册服务都需要这个地址</span>
			<span class="hljs-attr">defaultZone:</span> <span class="hljs-attr">http://${eureka.instance.hostname}:${server.port}/eureka</span>
</div></code></pre>
<p>在程序<strong>入口的类上加上@EnableEurekaServer注解</strong></p>
<p>访问localhost:端口,出现管理页面说明配置成功</p>
<p>client注册：</p>
<pre><code class="language-yml"><div><span class="hljs-attr">spring:</span>
	<span class="hljs-attr">application:</span> 
		<span class="hljs-attr">name:</span> <span class="hljs-string">应用名就是euraka的注册名</span>
<span class="hljs-attr">eureka:</span>
	<span class="hljs-attr">instance:</span>
		<span class="hljs-attr">hostname:</span> <span class="hljs-string">localhost</span> <span class="hljs-comment"># eureka服务端的实例名称</span>
	<span class="hljs-attr">client:</span> 
		<span class="hljs-comment"># 默认是true，注册到注册中心</span>
		<span class="hljs-attr">register-with-eureka:</span> <span class="hljs-literal">true</span>
		<span class="hljs-comment"># 默认是true， eureka是否抓取已有的注册中心</span>
		<span class="hljs-attr">fetch-registry:</span> <span class="hljs-literal">false</span>
		<span class="hljs-attr">service-url:</span>
			<span class="hljs-comment"># 设置与Eureka Server交互的地址查询服务和注册服务都需要这个地址</span>
			<span class="hljs-attr">defaultZone:</span> <span class="hljs-attr">http://localhost:端口/ereka</span> <span class="hljs-comment"># 配置eureka服务端的地址</span>
</div></code></pre>
<p>在程序入口的类上加上@EnableEurekaClient注解</p>
<h4 id="集群">集群</h4>
<p>​	相互注册，相互守望</p>
<p>​	服务端: server-url: defaultZone配置除自身以外的url</p>
<p>​	客户端：加入所有的服务端访问地址，客户端想使用集群使用@LoadBalanced注解</p>
<h3 id="zookeepercp-一致容错">Zookeeper（CP， 一致、容错）</h3>
<p>分布式协调技术:主要用来解决<strong>分布式环境</strong>当中<strong>多个进程之间</strong>的同步控制。</p>
<h4 id="网络存在的问题">网络存在的问题</h4>
<p>在分布式环境中，由于网络的不可靠，你对一个服务的调用失败了并不表示一定是失败的，可能是执行成功了，但是响应返回的时候失败了。还有，A和B都去调用C服务，在时间上 A还先调用一些，B后调用，那么最后的结果是不是一定A的请求就先于B到达呢？</p>
<h4 id="分布式锁的实现者">分布式锁的实现者</h4>
<h5 id="chubby谷歌自家的">chubby谷歌自家的</h5>
<p><img src="file:///e:\notepad\notepad\springboot\spring%E5%9F%BA%E7%A1%80\assets\1228818-20180321183640661-941556187.png" alt="img"></p>
<h5 id="zookeeper雅虎开源">Zookeeper雅虎开源</h5>
<p><img src="file:///e:\notepad\notepad\springboot\spring%E5%9F%BA%E7%A1%80\assets\1228818-20180321183649854-1229808958.png" alt="img"></p>
<h4 id="下载zookeeper">下载ZooKeeper</h4>
<p>要在你的计算机上安装ZooKeeper框架，请访问以下链接并下载最新版本的ZooKeeper。<a href="http://zookeeper.apache.org/releases.html">http://zookeeper.apache.org/releases.html</a></p>
<p>到目前为止，最新版本的ZooKeeper是3.4.6(ZooKeeper-3.4.6.tar.gz)。</p>
<h4 id="创建配置文件">创建配置文件</h4>
<p>使用命令 <strong>vi conf/zoo.cfg</strong> 和所有以下参数设置为起点，打开名为 <strong>conf/zoo.cfg</strong> 的配置文件。</p>
<pre><code class="language-bash"><div>$ vi conf/zoo.cfg

tickTime = 2000
dataDir = /path/to/zookeeper/data
clientPort = 2181
initLimit = 5
syncLimit = 2
</div></code></pre>
<p>一旦成功保存配置文件，再次返回终端。你现在可以启动zookeeper服务器。</p>
<h4 id="启动zookeeper服务器">启动ZooKeeper服务器</h4>
<p>执行以下命令</p>
<pre><code class="language-bash"><div>$ bin/zkServer.sh start
</div></code></pre>
<p>执行此命令后，你将收到以下响应</p>
<pre><code class="language-bash"><div>$ JMX enabled by default
$ Using config: /Users/../zookeeper-3.4.6/bin/../conf/zoo.cfg
$ Starting zookeeper ... STARTED
</div></code></pre>
<h4 id="启动cli">启动CLI</h4>
<p>键入以下命令</p>
<pre><code class="language-bash"><div>$ bin/zkCli.sh
</div></code></pre>
<p>键入上述命令后，将连接到ZooKeeper服务器，你应该得到以下响应。</p>
<pre><code class="language-bash"><div>Connecting to localhost:2181
................
................
................
Welcome to ZooKeeper!
................
................
WATCHER::
WatchedEvent state:SyncConnected <span class="hljs-built_in">type</span>: None path:null
[zk: localhost:2181(CONNECTED) 0]
</div></code></pre>
<h4 id="停止zookeeper服务器">停止ZooKeeper服务器</h4>
<p>连接服务器并执行所有操作后，可以使用以下命令停止zookeeper服务器。</p>
<pre><code class="language-bash"><div>$ bin/zkServer.sh stop
</div></code></pre>
<h4 id="依赖">依赖</h4>
<pre><code class="language-xml"><div><span class="hljs-tag">&lt;<span class="hljs-name">dependency</span>&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">groupId</span>&gt;</span>org.springframework.cloud<span class="hljs-tag">&lt;/<span class="hljs-name">groupId</span>&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">artifactId</span>&gt;</span>spring-cloud-starter-zookeeper-discovery<span class="hljs-tag">&lt;/<span class="hljs-name">artifactId</span>&gt;</span>
<span class="hljs-tag">&lt;/<span class="hljs-name">dependency</span>&gt;</span>
</div></code></pre>
<h4 id="配置">配置</h4>
<pre><code class="language-yml"><div><span class="hljs-attr">spring:</span>
<span class="hljs-attr">  cloud:</span>
<span class="hljs-attr">    zookeeper:</span>
<span class="hljs-attr">      connect-string:</span> <span class="hljs-attr">master:2181</span>  <span class="hljs-comment"># 必须加</span>
<span class="hljs-attr">      max-retries:</span> <span class="hljs-number">3</span> <span class="hljs-comment"># 最大尝试次数</span>
<span class="hljs-attr">      base-sleep-time-ms:</span> <span class="hljs-number">1000</span> <span class="hljs-comment"># 初始化休眠时间</span>
</div></code></pre>
<p>启动类加注解@EnableDiscoveryClient</p>
<p>zookeeper： ls 查看服务是否注入</p>
<h3 id="consulcp一致容错">Consul（CP，一致、容错）</h3>
<h4 id="概述">概述</h4>
<p>代理是指consul集群中运行的<strong>consul实例</strong>，通过执行 consul agent 命令来启动. 代理可以运行于客户端或者服务端。</p>
<p>官网：<a href="https://www.consul.io/downloads.html">https://www.consul.io/downloads.html</a></p>
<h4 id="安装">安装</h4>
<pre><code class="language-bash"><div>yum install -y unzip
unzip -d 解压路径 文件
</div></code></pre>
<h4 id="启动">启动</h4>
<pre><code class="language-bash"><div>./consul 命令 --<span class="hljs-built_in">help</span> <span class="hljs-comment"># 查看用法</span>
</div></code></pre>
<pre><code class="language-bash"><div><span class="hljs-comment"># 持久化启动：</span>
./consul agent -server -ui -bootstrap-expect=1 -data-dir=/tmp/consul -node=agent-one -advertise=0.0.0.0 -<span class="hljs-built_in">bind</span>=0.0.0.0 -client=10.224.162.189

<span class="hljs-comment"># 在使用 -server 参数启动单节点的时候可能会一直出现leader选举失败的情况。</span>
./consul agent -dev -ui -bootstrap-expect=1 -data-dir=/tmp/consul [-node=节点名称] -client=10.224.162.189

</div></code></pre>
<ul>
<li>节点名称：这是代理的唯一名称。默认情况下，这是机器的主机名，但可以使用 <code>-node</code>标志对其进行自定义。</li>
<li><code>-dev</code>：开发服务器模式,虽然是server模式，但<strong>不用于生产环境</strong>，因为不会有任何持久化操作，即<strong>不会有任何数据写入到磁盘</strong></li>
<li><code>-server</code>：定义agent运行在server模式，每个集群至少有一个server，建议每个集群的server不要超过5个</li>
<li><code>-client</code>：consul绑定在哪个client地址上，这个地址提供HTTP、DNS、RPC等服务，默认是127.0.0.1</li>
<li><code>-data-dir</code>：指定agent储存状态的数据目录，这是所有agent都必须的,<strong>对server尤其重要</strong>，因为他们必须持久化集群的状态。</li>
<li><code>-config-dir</code>：配置文件目录，目录必须为 <code>consul.d</code>，文件内容都是 json 格式数据，里面所有以.json结尾的文件都会被加载。</li>
<li><code>-config-file</code>：明确的指定要加载哪个配置文件。</li>
<li>-bootstrap-expect：<strong>Sets</strong> <strong>server</strong> <strong>to</strong> expect bootstrap mode.</li>
<li>-ui Enables the built-<strong>in</strong> <strong>static</strong> web UI <strong>server</strong></li>
<li>数据中心：这是配置代理运行的数据中心。每个节点都必须设置其它向数据中心报告。<code>-datacenter</code> 标志可用于设置数据中心。对于单DC配置，代理将默认为“dc1”。</li>
</ul>
<h4 id="依赖-1">依赖</h4>
<pre><code class="language-xml"><div><span class="hljs-tag">&lt;<span class="hljs-name">dependency</span>&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">groupId</span>&gt;</span>org.springframework.cloud<span class="hljs-tag">&lt;/<span class="hljs-name">groupId</span>&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">artifactId</span>&gt;</span>spring-cloud-starter-consul-discovery<span class="hljs-tag">&lt;/<span class="hljs-name">artifactId</span>&gt;</span>
<span class="hljs-tag">&lt;/<span class="hljs-name">dependency</span>&gt;</span>
</div></code></pre>
<h4 id="yaml配置">yaml配置</h4>
<pre><code class="language-yml"><div><span class="hljs-attr">spring:</span>
<span class="hljs-attr">  cloud:</span>
<span class="hljs-attr">    consul:</span>
<span class="hljs-attr">      host:</span> <span class="hljs-string">localhost</span> <span class="hljs-comment"># consul的ip</span>
<span class="hljs-attr">      port:</span> <span class="hljs-number">8500</span> <span class="hljs-comment"># consul的端口</span>
</div></code></pre>
<h3 id="nacos">Nacos</h3>
<h4 id="下载地址">下载地址</h4>
<p><a href="https://github.com/alibaba/nacos/releases">https://github.com/alibaba/nacos/releases</a></p>
<h4 id="启动命令">启动命令</h4>
<pre><code class="language-bash"><div><span class="hljs-comment"># 启动命令(standalone代表着单机模式运行，非集群模式)</span>
startup.sh -m standalone
<span class="hljs-comment"># 关闭命令</span>
shutdown.sh
</div></code></pre>
<h4 id="web管理界面">web管理界面</h4>
<p><a href="http://localhost:8848/nacos/">http://localhost:8848/nacos/</a></p>
<p>第一次使用：</p>
<pre><code class="language-bash"><div>account: nacos
password: nacos
</div></code></pre>
<h4 id="依赖-2">依赖</h4>
<pre><code class="language-xml"><div><span class="hljs-tag">&lt;<span class="hljs-name">dependency</span>&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">groupId</span>&gt;</span>com.alibaba.cloud<span class="hljs-tag">&lt;/<span class="hljs-name">groupId</span>&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">artifactId</span>&gt;</span>spring-cloud-alibaba-dependencies<span class="hljs-tag">&lt;/<span class="hljs-name">artifactId</span>&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">version</span>&gt;</span>${spring.cloud.alibaba.version}<span class="hljs-tag">&lt;/<span class="hljs-name">version</span>&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">type</span>&gt;</span>pom<span class="hljs-tag">&lt;/<span class="hljs-name">type</span>&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">scope</span>&gt;</span>import<span class="hljs-tag">&lt;/<span class="hljs-name">scope</span>&gt;</span>
<span class="hljs-tag">&lt;/<span class="hljs-name">dependency</span>&gt;</span>
</div></code></pre>
<pre><code class="language-xml"><div><span class="hljs-tag">&lt;<span class="hljs-name">dependency</span>&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">groupId</span>&gt;</span>com.alibaba.cloud<span class="hljs-tag">&lt;/<span class="hljs-name">groupId</span>&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">artifactId</span>&gt;</span>spring-cloud-starter-alibaba-nacos-discovery<span class="hljs-tag">&lt;/<span class="hljs-name">artifactId</span>&gt;</span>
<span class="hljs-tag">&lt;/<span class="hljs-name">dependency</span>&gt;</span>
</div></code></pre>
<h4 id="配置-1">配置</h4>
<pre><code class="language-yml"><div><span class="hljs-attr">spring:</span>
<span class="hljs-attr">  cloud:</span>
<span class="hljs-attr">    nacos:</span>
<span class="hljs-attr">      discovery:</span>
<span class="hljs-attr">        server-addr:</span> <span class="hljs-attr">master:8848</span> <span class="hljs-comment">#配置Nacos地址</span>
</div></code></pre>
<h2 id="负载均衡服务调用">负载均衡服务调用</h2>
<h3 id="ribbon一个工具类框架">Ribbon(一个工具类框架)</h3>
<h4 id="概述-1">概述</h4>
<h5 id="主流的负载均衡">主流的负载均衡：</h5>
<ol>
<li>
<p>集中式负载均衡,在消费者和服务提供者中间使用独立的代理方式进行负载均衡,例如：Nginx</p>
</li>
<li>
<p>客户端自己做负载均衡，更具自己的请求情况做负载，Ribbon</p>
</li>
</ol>
<p>Spring Cloud Ribbon是一个基于HTTP和TCP的客户端负载均衡工具,它基于Netflix Ribbon实现。通过Spring Cloud的封装，可以轻松地将面向服务的Rest模板请求自动转换为客户端<strong>负载均衡的</strong>服务调用。</p>
<p>SpringCloud Ribbon属于工具类框架，它不像服务注册中心、配置中心、API网关那样需要独立部署。</p>
<h3 id="ribbon-模块">Ribbon 模块</h3>
<table>
<thead>
<tr>
<th>名 称</th>
<th>说  明</th>
</tr>
</thead>
<tbody>
<tr>
<td>ribbon-loadbalancer</td>
<td>负载均衡模块，可独立使用，也可以和别的模块一起使用。</td>
</tr>
<tr>
<td>Ribbon</td>
<td>内置的负载均衡算法都实现在其中。</td>
</tr>
<tr>
<td>ribbon-eureka</td>
<td>基于 Eureka 封装的模块，能够快速、方便地集成 Eureka。</td>
</tr>
<tr>
<td>ribbon-transport</td>
<td>基于 Netty 实现多协议的支持，比如 HTTP、Tcp、Udp 等。</td>
</tr>
<tr>
<td>ribbon-httpclient</td>
<td>基于 Apache HttpClient 封装的 REST 客户端，集成了负载均衡模块，可以直接在项目中使用来调用接口。</td>
</tr>
<tr>
<td>ribbon-example</td>
<td>Ribbon 使用代码示例，通过这些示例能够让你的学习事半功倍。</td>
</tr>
<tr>
<td>ribbon-core</td>
<td>一些比较核心且具有通用性的代码，客户端 API 的一些配置和其他 API 的定义。</td>
</tr>
</tbody>
</table>
<h2 id="ribbon-使用">Ribbon 使用</h2>
<p>我们使用 Ribbon 来实现一个最简单的负载均衡调用功能，接口就用/user/hello 接口，需要启动两个服务，一个是 8081 的端口，一个是 8083 的端口。</p>
<p>然后创建一个新的 <a href="http://c.biancheng.net/maven/">Maven</a> 项目 ribbon-native-demo，在项目中集成 Ribbon，在 pom.xml 中添加如下代码所示的依赖。</p>
<pre><code class="language-xml"><div><span class="hljs-tag">&lt;<span class="hljs-name">dependency</span>&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">groupId</span>&gt;</span>com.netflix.ribbon<span class="hljs-tag">&lt;/<span class="hljs-name">groupId</span>&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">artifactId</span>&gt;</span>ribbon<span class="hljs-tag">&lt;/<span class="hljs-name">artifactId</span>&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">version</span>&gt;</span>2.2.2<span class="hljs-tag">&lt;/<span class="hljs-name">version</span>&gt;</span>
<span class="hljs-tag">&lt;/<span class="hljs-name">dependency</span>&gt;</span>
<span class="hljs-tag">&lt;<span class="hljs-name">dependency</span>&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">groupId</span>&gt;</span>com.netflix.ribbon<span class="hljs-tag">&lt;/<span class="hljs-name">groupId</span>&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">artifactId</span>&gt;</span>ribbon-core<span class="hljs-tag">&lt;/<span class="hljs-name">artifactId</span>&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">version</span>&gt;</span>2.2.2<span class="hljs-tag">&lt;/<span class="hljs-name">version</span>&gt;</span>
<span class="hljs-tag">&lt;/<span class="hljs-name">dependency</span>&gt;</span>
<span class="hljs-tag">&lt;<span class="hljs-name">dependency</span>&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">groupId</span>&gt;</span>com.netflix.ribbon<span class="hljs-tag">&lt;/<span class="hljs-name">groupId</span>&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">artifactId</span>&gt;</span>ribbon-loadbalancer<span class="hljs-tag">&lt;/<span class="hljs-name">artifactId</span>&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">version</span>&gt;</span>2.2.2<span class="hljs-tag">&lt;/<span class="hljs-name">version</span>&gt;</span>
<span class="hljs-tag">&lt;/<span class="hljs-name">dependency</span>&gt;</span>
<span class="hljs-tag">&lt;<span class="hljs-name">dependency</span>&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">groupId</span>&gt;</span>io.reactivex<span class="hljs-tag">&lt;/<span class="hljs-name">groupId</span>&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">artifactId</span>&gt;</span>rxjava<span class="hljs-tag">&lt;/<span class="hljs-name">artifactId</span>&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">version</span>&gt;</span>1.0.10<span class="hljs-tag">&lt;/<span class="hljs-name">version</span>&gt;</span>
<span class="hljs-tag">&lt;/<span class="hljs-name">dependency</span>&gt;</span>
</div></code></pre>
<p>接下来我们编写一个客户端来调用接口，代码如下所示。</p>
<pre><code><code><div>// 服务列表
List&lt;Server&gt; serverList = Lists.newArrayList(new Server(&quot;localhost&quot;, 8081), new Server(&quot;localhost&quot;, 8083));
// 构建负载实例
ILoadBalancer loadBalancer = LoadBalancerBuilder.newBuilder().buildFixedServerListLoadBalancer(serverList);
// 调用 5 次来测试效果
for (int i = 0; i &lt; 5; i++) {
    String result = LoadBalancerCommand.&lt;String&gt;builder().withLoadBalancer(loadBalancer).build()
            .submit(new ServerOperation&lt;String&gt;() {
                public Observable&lt;String&gt; call(Server server) {
                    try {
                        String addr = &quot;http://&quot; + server.getHost() + &quot;:&quot; + server.getPort() + &quot;/user/hello&quot;;
                        System.out.println(&quot; 调用地址：&quot; + addr);
                        URL url = new URL(addr);
                        HttpURLConnection conn = (HttpURLConnection) url.openConnection();
                        conn.setRequestMethod(&quot;GET&quot;);
                        conn.connect();
                        InputStream in = conn.getInputStream();
                        byte[] data = new byte[in.available()];
                        in.read(data);
                        return Observable.just(new String(data));
                    } catch (Exception e) {
                        return Observable.error(e);
                    }
                }
            }).toBlocking().first();
    System.out.println(&quot; 调用结果：&quot; + result);
}
</div></code></code></pre>
<p>上述这个例子主要演示了 Ribbon 如何去做负载操作，调用接口用的最底层的 HttpURLConnection。当然你也可以用别的客户端，或者直接用 RibbonClient 执行程序，可以看到控制台输出的结果如下：</p>
<p><img src="http://c.biancheng.net/uploads/allimg/190821/5-1ZR1123520647.png" alt="控制台输出结果"></p>
<p><strong>说明ribbon可以独立调用</strong></p>
<h3 id="spring-cloud-ribbon项目">Spring Cloud Ribbon项目</h3>
<h4 id="使用resttemplate与ribbon">使用RestTemplate与Ribbon</h4>
<pre><code class="language-java"><div><span class="hljs-meta">@Configuration</span>
<span class="hljs-keyword">public</span> <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">BeanConfiguration</span> </span>{
    <span class="hljs-meta">@Bean</span>
    <span class="hljs-meta">@LoadBalanced</span> <span class="hljs-comment">// Eureka 默认集成了Ribbon, 所以我们能直接使用</span>
    <span class="hljs-function"><span class="hljs-keyword">public</span> RestTemplate <span class="hljs-title">getRestTemplate</span><span class="hljs-params">()</span> </span>{
        <span class="hljs-keyword">return</span> <span class="hljs-keyword">new</span> RestTemplate();
    }
}
</div></code></pre>
<pre><code class="language-xml"><div><span class="hljs-comment">&lt;!-- 引入依赖 --&gt;</span>
<span class="hljs-tag">&lt;<span class="hljs-name">dependency</span>&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">groupId</span>&gt;</span>org.springframework.cloud<span class="hljs-tag">&lt;/<span class="hljs-name">groupId</span>&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">artifactId</span>&gt;</span>spring-cloud-starter-netflix-ribbon<span class="hljs-tag">&lt;/<span class="hljs-name">artifactId</span>&gt;</span>
<span class="hljs-tag">&lt;/<span class="hljs-name">dependency</span>&gt;</span>
</div></code></pre>
<p>Q: 为什么在 RestTemplate 上加了一个 @LoadBalanced 之后，RestTemplate 就能够跟 Eureka 结合了，不但可以使用服务名称去调用接口，还可以负载均衡？</p>
<p>A: 这里主要的逻辑就是给 RestTemplate 增加拦截器，在请求之前对请求的地址进行替换，或者根据具体的负载策略选择服务地址，然后再去调用，这就是 @LoadBalanced 的原理。</p>
<pre><code class="language-java"><div><span class="hljs-comment">// 创建拦截器</span>
<span class="hljs-keyword">public</span> <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">MyLoadBalancerInterceptor</span> <span class="hljs-keyword">implements</span> <span class="hljs-title">ClientHttpRequestInterceptor</span> </span>{
    <span class="hljs-keyword">private</span> LoadBalancerClient loadBalancer;
    <span class="hljs-keyword">private</span> LoadBalancerRequestFactory requestFactory;
    <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-title">MyLoadBalancerInterceptor</span><span class="hljs-params">(LoadBalancerClient loadBalancer, LoadBalancerRequestFactory requestFactory)</span> </span>{
        <span class="hljs-keyword">this</span>.loadBalancer = loadBalancer;
        <span class="hljs-keyword">this</span>.requestFactory = requestFactory;
    }
    <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-title">MyLoadBalancerInterceptor</span><span class="hljs-params">(LoadBalancerClient loadBalancer)</span> </span>{
        <span class="hljs-keyword">this</span>(loadBalancer, <span class="hljs-keyword">new</span> LoadBalancerRequestFactory(loadBalancer));
    }
    <span class="hljs-meta">@Override</span>
    <span class="hljs-function"><span class="hljs-keyword">public</span> ClientHttpResponse <span class="hljs-title">intercept</span><span class="hljs-params">(<span class="hljs-keyword">final</span> HttpRequest request, <span class="hljs-keyword">final</span> <span class="hljs-keyword">byte</span>[] body,
            <span class="hljs-keyword">final</span> ClientHttpRequestExecution execution)</span> <span class="hljs-keyword">throws</span> IOException </span>{
        <span class="hljs-keyword">final</span> URI originalUri = request.getURI();
        String serviceName = originalUri.getHost();
        System.out.println(<span class="hljs-string">"进入自定义的请求拦截器中"</span> + serviceName);
        Assert.state(serviceName != <span class="hljs-keyword">null</span>, <span class="hljs-string">"Request URI does not contain a valid hostname: "</span> + originalUri);
        <span class="hljs-keyword">return</span> <span class="hljs-keyword">this</span>.loadBalancer.execute(serviceName, requestFactory.createRequest(request, body, execution));
    }
}
</div></code></pre>
<p>拦截器设置好了之后，我们再定义一个注解，并复制 @LoadBalanced 的代码，改个名称就可以了，代码如下所示。</p>
<pre><code class="language-java"><div><span class="hljs-meta">@Target</span>({ ElementType.FIELD, ElementType.PARAMETER, ElementType.METHOD })
<span class="hljs-meta">@Retention</span>(RetentionPolicy.RUNTIME)
<span class="hljs-meta">@Documented</span>
<span class="hljs-meta">@Inherited</span>
<span class="hljs-meta">@Qualifier</span>
<span class="hljs-keyword">public</span> <span class="hljs-meta">@interface</span> MyLoadBalanced {
}
</div></code></pre>
<p>然后定义一个配置类，给 RestTemplate 注入拦截器，代码如下所示。</p>
<pre><code class="language-java"><div><span class="hljs-meta">@Configuration</span>
<span class="hljs-keyword">public</span> <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">MyLoadBalancerAutoConfiguration</span> </span>{
    <span class="hljs-meta">@MyLoadBalanced</span>
    <span class="hljs-meta">@Autowired</span>(required = <span class="hljs-keyword">false</span>)
    <span class="hljs-keyword">private</span> List&lt;RestTemplate&gt; restTemplates = Collections.emptyList();
    <span class="hljs-meta">@Bean</span>
    <span class="hljs-function"><span class="hljs-keyword">public</span> MyLoadBalancerInterceptor <span class="hljs-title">myLoadBalancerInterceptor</span><span class="hljs-params">()</span> </span>{
        <span class="hljs-keyword">return</span> <span class="hljs-keyword">new</span> MyLoadBalancerInterceptor();
    }
    <span class="hljs-meta">@Bean</span>
    <span class="hljs-function"><span class="hljs-keyword">public</span> SmartInitializingSingleton <span class="hljs-title">myLoadBalancedRestTemplateInitializer</span><span class="hljs-params">()</span> </span>{
        <span class="hljs-keyword">return</span> <span class="hljs-keyword">new</span> SmartInitializingSingleton() {
          <span class="hljs-meta">@Override</span>
          <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title">afterSingletonsInstantiated</span><span class="hljs-params">()</span> </span>{
            <span class="hljs-keyword">for</span> (RestTemplate restTemplate : MyLoadBalancerAutoConfiguration.<span class="hljs-keyword">this</span>.restTemplates){
                List&lt;ClientHttpRequestInterceptor&gt; list = <span class="hljs-keyword">new</span> ArrayList&lt;&gt;(restTemplate.getInterceptors());
                list.add(<span class="hljs-function">myLoad <span class="hljs-title">BalancerInterceptor</span><span class="hljs-params">()</span>)</span>;
                restTemplate.setInterceptors(list);
            }
          }
        };
    }
}
</div></code></pre>
<p>维护一个 @MyLoadBalanced 的 RestTemplate 列表，在 SmartInitializingSingleton 中对 RestTemplate 进行拦截器设置。</p>
<p>然后改造我们之前的 RestTemplate 配置，将 @LoadBalanced 改成我们自定义的 @MyLoadBalanced，代码如下所示。</p>
<pre><code class="language-java"><div><span class="hljs-meta">@Bean</span>
<span class="hljs-comment">//@LoadBalanced</span>
<span class="hljs-meta">@MyLoadBalanced</span>
<span class="hljs-function"><span class="hljs-keyword">public</span> RestTemplate <span class="hljs-title">getRestTemplate</span><span class="hljs-params">()</span> </span>{
  <span class="hljs-keyword">return</span> <span class="hljs-keyword">new</span> RestTemplate();
}
</div></code></pre>
<p>重启服务，访问服务中的接口就可以看到控制台的输出了，这证明在接口调用的时候会进入该拦截器，输出如下：</p>
<p>进入自定义的请求拦截器中 ribbon-eureka-demo</p>
<pre><code class="language-bash"><div><span class="hljs-comment"># 进入自定义的请求拦截器中 ribbon-eureka-demo</span>
</div></code></pre>
<h3 id="ribbon-api-使用">Ribbon API 使用</h3>
<p>当你有一些特殊的需求，想通过 Ribbon 获取对应的服务信息时，可以使用 Load-Balancer Client 来获取，比如你想获取一个 ribbon-eureka-demo 服务的服务地址，可以通过 LoadBalancerClient 的 choose 方法来选择一个：</p>
<pre><code class="language-java"><div><span class="hljs-meta">@Autowired</span>
<span class="hljs-keyword">private</span> LoadBalancerClient loadBalancer;
<span class="hljs-meta">@GetMapping</span>(<span class="hljs-string">"/choose"</span>)
<span class="hljs-function"><span class="hljs-keyword">public</span> Object <span class="hljs-title">chooseUrl</span><span class="hljs-params">()</span> </span>{
    ServiceInstance instance = loadBalancer.choose(<span class="hljs-string">"ribbon-eureka-demo"</span>);
    <span class="hljs-keyword">return</span> instance;
}
</div></code></pre>
<p>访问接口，可以看到返回的信息如下：</p>
<pre><code class="language-json"><div>{
    serviceId: <span class="hljs-string">"ribbon-eureka-demo"</span>,
    server: {
        host: <span class="hljs-string">"localhost"</span>,
        port: <span class="hljs-number">8081</span>,
        id: <span class="hljs-string">"localhost:8081"</span>,
        zone: <span class="hljs-string">"UNKNOWN"</span>,
        readyToServe: <span class="hljs-literal">true</span>,
        alive: <span class="hljs-literal">true</span>,
        hostPort: <span class="hljs-string">"localhost:8081"</span>,
        metaInfo: {
            serverGroup: <span class="hljs-literal">null</span>,
            serviceIdForDiscovery: <span class="hljs-literal">null</span>, instanceId: <span class="hljs-string">"localhost:8081"</span>,
            appName: <span class="hljs-literal">null</span>
        }
    },
    secure: <span class="hljs-literal">false</span>, metadata: { }, host: <span class="hljs-string">"localhost"</span>, port: <span class="hljs-number">8081</span>,
    uri: <span class="hljs-string">"http://localhost:8081"</span>
}
</div></code></pre>
<h3 id="ribbon-饥饿加载">Ribbon 饥饿加载</h3>
<p>笔者从网上看到很多博客中都提到过的一种情况：在进行服务调用的时候，如果网络情况不好，第一次调用会超时。有很多大神对此提出了解决方案，比如把超时时间改长一点、禁用超时等。</p>
<p>Spring Cloud 目前正在高速发展中，版本更新很快，我们能发现的问题基本上在版本更新的时候就修复了，或者提供最优的解决方案。</p>
<p>超时的问题也是一样，Ribbon 的客户端是在第一次请求的时候初始化的，如果超时时间比较短的话，初始化 Client 的时间再加上请求接口的时间，就会导致第一次请求超时。</p>
<p>本教程是基于 Finchley.SR2 撰写的，这个版本已经提供了一种针对上述问题的解决方法，那就是 eager-load 方式。通过配置 eager-load 来提前初始化客户端就可以解决这个问题。</p>
<pre><code class="language-properties"><div><span class="hljs-meta">ribbon.eager-load.enabled</span>=<span class="hljs-string">true</span>
<span class="hljs-meta">ribbon.eager-load.clients</span>=<span class="hljs-string">ribbon-eureka-demo</span>
</div></code></pre>
<ul>
<li>ribbon.eager-load.enabled：开启 Ribbon 的饥饿加载模式。</li>
<li>ribbon.eager-load.clients：指定需要饥饿加载的服务名，也就是你需要调用的服务，若有多个则用逗号隔开。</li>
</ul>
<h3 id="ribbon负载均衡策略默认轮询">Ribbon负载均衡策略（默认轮询）</h3>
<h4 id="自定义负载均衡策略重点">自定义负载均衡策略（重点！！！）</h4>
<h2 id="loadbalancer">LoadBalancer</h2>
<p>Spring Cloud不仅提供了使用<strong>Ribbon</strong>进行客户端负载均衡，还提供了<strong>Spring Cloud LoadBalancer</strong>。相比较于Ribbon，Spring Cloud LoadBalancer不仅能够支持<strong>RestTemplate</strong>，还支持<strong>WebClient</strong>。WeClient是<strong>Spring Web Flux</strong>中提供的功能，可以实现响应式异步请求，因此学习Spring Cloud LoadBalancer之前，建议先了解下Spring Web Flux。</p>
<p>如果在项目的类路径下存在Spring Cloud Ribbon相关的类，需要通过配置关闭Ribbon功能，因为Spring Cloud默认优先使用Ribbon：</p>
<pre><code><code><div>spring:
	cloud:
		loadbalancer:
			ribbon:
				enabled: false
</div></code></code></pre>
<p>需要在方法上标注@LoadBalanced注解。</p>
<h1 id="spring-常用配置">Spring 常用配置</h1>
<h2 id="常用配置属性">常用配置属性</h2>
<h3 id="分区配置">分区配置</h3>
<pre><code class="language-yml"><div><span class="hljs-comment"># 分区配置，在开发测试时和生产环境可能不一样</span>
<span class="hljs-comment"># 按照SpringBoot的约束： application-{profile}.yml来配置多个文件， 然后使用application.yml中的以下配置激活文件</span>
<span class="hljs-attr">spring:</span>
<span class="hljs-attr">  profiles:</span>
<span class="hljs-attr">    active:</span> <span class="hljs-string">{profile}</span>
<span class="hljs-comment"># application-{profile}.yml 可以放的位置：</span>
<span class="hljs-comment"># 1. 当前目录下</span>
<span class="hljs-comment"># 2. 当前目录下的“/config”目录下</span>
<span class="hljs-comment"># 3. classpath目录下</span>
<span class="hljs-comment"># 4. classpath的“/config”目录下</span>
</div></code></pre>
<p>测试案例：</p>
<p>我们在application.properyies也写上，并把profile切换到application-cus1.properties的配置文件</p>
<pre><code class="language-yml"><div><span class="hljs-string">cusvar=cus3</span>
<span class="hljs-string">spring.profiles.active=cus1</span>
</div></code></pre>
<p>可以通过这样子来测试</p>
<pre><code class="language-java"><div> 复制
<span class="hljs-meta">@RestController</span>
<span class="hljs-meta">@RequestMapping</span>(<span class="hljs-string">"/task"</span>)
<span class="hljs-keyword">public</span> <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">TaskController</span> </span>{

    <span class="hljs-meta">@RequestMapping</span>(value = {<span class="hljs-string">"/"</span>,<span class="hljs-string">""</span>})
    <span class="hljs-function"><span class="hljs-keyword">public</span> String <span class="hljs-title">hellTask</span><span class="hljs-params">(@Value(<span class="hljs-string">"${cusvar}"</span>)</span>String cusvar )</span>{

        <span class="hljs-keyword">return</span> <span class="hljs-string">"hello task !! myage is "</span> + cusvar;
    }

}
</div></code></pre>
<p>在这里可以看到spring.profiles.active激活的profile不同，打印出来的结果也不一样。</p>
<p>除了使用配置文件还可以使用@Profile注解</p>
<p>除了可以用profile的配置文件来分区配置我们的环境变量，在代码里，我们还可以直接用@Profile注解来进行配置，例如数据库配置，这里我们先定义一个接口</p>
<pre><code class="language-java"><div> <span class="hljs-keyword">public</span> <span class="hljs-class"><span class="hljs-keyword">interface</span> <span class="hljs-title">DBConnector</span> </span>{
    <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title">configure</span><span class="hljs-params">()</span></span>;    
}
</div></code></pre>
<p>分别定义俩个实现类来实现它</p>
<pre><code class="language-java"><div> <span class="hljs-comment">/**
  * 测试数据库
  */</span>
<span class="hljs-meta">@Component</span>
<span class="hljs-meta">@Profile</span>(<span class="hljs-string">"testdb"</span>)
<span class="hljs-keyword">public</span> <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">TestDBConnector</span> <span class="hljs-keyword">implements</span> <span class="hljs-title">DBConnector</span> </span>{

    <span class="hljs-meta">@Override</span>
    <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title">configure</span><span class="hljs-params">()</span> </span>{

        System.out.println(<span class="hljs-string">"testdb"</span>);

    }
}

<span class="hljs-comment">/**
 * 生产数据库
 */</span>
<span class="hljs-meta">@Component</span>
<span class="hljs-meta">@Profile</span>(<span class="hljs-string">"devdb"</span>)
<span class="hljs-keyword">public</span> <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">DevDBConnector</span> <span class="hljs-keyword">implements</span> <span class="hljs-title">DBConnector</span> </span>{

    <span class="hljs-meta">@Override</span>
    <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title">configure</span><span class="hljs-params">()</span> </span>{

        System.out.println(<span class="hljs-string">"devdb"</span>);

    }

}
</div></code></pre>
<p>通过在配置文件激活具体使用哪个实现类</p>
<pre><code class="language-yml"><div> <span class="hljs-string">spring.profiles.active=testdb</span>
</div></code></pre>
<p>测试案例：</p>
<pre><code class="language-java"><div><span class="hljs-meta">@RestController</span>
<span class="hljs-meta">@RequestMapping</span>(<span class="hljs-string">"/task"</span>)
<span class="hljs-keyword">public</span> <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">TaskController</span> </span>{

    <span class="hljs-meta">@Autowired</span> DBConnector connector ;

    <span class="hljs-meta">@RequestMapping</span>(value = {<span class="hljs-string">"/"</span>,<span class="hljs-string">""</span>})
    <span class="hljs-function"><span class="hljs-keyword">public</span> String <span class="hljs-title">hellTask</span><span class="hljs-params">()</span></span>{

        connector.configure(); <span class="hljs-comment">//修改 spring.profiles.active就能改变</span>
        <span class="hljs-keyword">return</span> <span class="hljs-string">"hello task !! myage is "</span> + myage;
    }

}
</div></code></pre>
<h2 id="跨站">跨站</h2>
<p>使用@CrossOrigin或者使用下面的代码配置</p>
<pre><code class="language-java"><div><span class="hljs-meta">@Configuration</span>
<span class="hljs-keyword">public</span> <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">CorsConfig</span> <span class="hljs-keyword">implements</span> <span class="hljs-title">WebMvcConfigurer</span> </span>{

    <span class="hljs-comment">/**
     * 页面跨域访问Controller过滤
     *
     * <span class="hljs-doctag">@return</span>
     */</span>
    <span class="hljs-meta">@Override</span>
    <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title">addCorsMappings</span><span class="hljs-params">(CorsRegistry registry)</span> </span>{
        WebMvcConfigurer.<span class="hljs-keyword">super</span>.addCorsMappings(registry);
        registry.addMapping(<span class="hljs-string">"/**"</span>)
                .allowedHeaders(<span class="hljs-string">"*"</span>)
                .allowedMethods(<span class="hljs-string">"POST"</span>,<span class="hljs-string">"GET"</span>)
                .allowedOrigins(<span class="hljs-string">"*"</span>);
    }
}
</div></code></pre>
<p><strong>使用spring.profiles.action激活多个文件</strong>在配置文件中使用</p>
<pre><code class="language-yml"><div><span class="hljs-comment"># 一般将开发放一套中，测试环境放一套中， 运行环境放一套中</span>
<span class="hljs-string">spring.profiles.include:</span> <span class="hljs-string">子项1,子项2,子项3</span>
<span class="hljs-string">spring.profiles.include:</span>
<span class="hljs-bullet">  -</span> <span class="hljs-string">子项1</span>
<span class="hljs-bullet">  -</span> <span class="hljs-string">子项2</span>
<span class="hljs-bullet">  -</span> <span class="hljs-string">子项3</span>   
</div></code></pre>
<h3 id="配置elasticsearch搜索引擎">配置elasticsearch搜索引擎</h3>
<pre><code class="language-yml"><div><span class="hljs-attr">spring:</span>
<span class="hljs-attr">  es:</span>
<span class="hljs-attr">    elasticsearch:</span>
<span class="hljs-attr">      cluster-name:</span> <span class="hljs-string">xxx</span>
<span class="hljs-attr">      ip:</span> <span class="hljs-string">ip地址</span>
<span class="hljs-attr">      port:</span> <span class="hljs-string">引擎端口号</span>
</div></code></pre>
<pre><code class="language-java"><div><span class="hljs-meta">@Value</span>(<span class="hljs-string">"${spring.es.elasticsearch.ip}"</span>)<span class="hljs-comment">//注入到String中</span>
</div></code></pre>
<h3 id="配置mybatis">配置mybatis</h3>
<pre><code class="language-yml"><div><span class="hljs-attr">mybatis:</span>
<span class="hljs-attr">  type-aliases-package:</span> <span class="hljs-string">实体对应的包</span>
<span class="hljs-attr">  mapper-locations:</span> <span class="hljs-attr">classpath:mapper的xml文件</span>
</div></code></pre>
<h3 id="配置邮件模块2x">配置邮件模块,2.x</h3>
<pre><code class="language-xml"><div><span class="hljs-tag">&lt;<span class="hljs-name">dependency</span>&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">groupId</span>&gt;</span>org.springframework.boot<span class="hljs-tag">&lt;/<span class="hljs-name">groupId</span>&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">artifactId</span>&gt;</span>spring-boot-starter-mail<span class="hljs-tag">&lt;/<span class="hljs-name">artifactId</span>&gt;</span>
<span class="hljs-tag">&lt;/<span class="hljs-name">dependency</span>&gt;</span>
</div></code></pre>
<pre><code class="language-yml"><div><span class="hljs-attr">spring:</span>
<span class="hljs-attr">  mail:</span>
<span class="hljs-attr">    host:</span> <span class="hljs-string">smtp.qq.com</span> <span class="hljs-comment">#发送邮件服务器</span>
<span class="hljs-attr">    username:</span> <span class="hljs-string">xx@qq.com</span> <span class="hljs-comment">#QQ邮箱</span>
<span class="hljs-attr">    password:</span> <span class="hljs-string">xxxxxxxxxxx</span> <span class="hljs-comment">#客户端授权码</span>
<span class="hljs-attr">    protocol:</span> <span class="hljs-string">smtp</span> <span class="hljs-comment">#发送邮件协议</span>
    <span class="hljs-string">properties.mail.smtp.auth:</span> <span class="hljs-literal">true</span>
    <span class="hljs-string">properties.mail.smtp.port:</span> <span class="hljs-number">465</span> <span class="hljs-comment">#端口号465或587</span>
    <span class="hljs-string">properties.mail.display.sendmail:</span> <span class="hljs-string">aaa</span> <span class="hljs-comment">#可以任意</span>
    <span class="hljs-string">properties.mail.display.sendname:</span> <span class="hljs-string">bbb</span> <span class="hljs-comment">#可以任意</span>
    <span class="hljs-string">properties.mail.smtp.starttls.enable:</span> <span class="hljs-literal">true</span>
    <span class="hljs-string">properties.mail.smtp.starttls.required:</span> <span class="hljs-literal">true</span>
    <span class="hljs-string">properties.mail.smtp.ssl.enable:</span> <span class="hljs-literal">true</span> <span class="hljs-comment">#开启SSL</span>
<span class="hljs-attr">    default-encoding:</span> <span class="hljs-string">utf-8</span>
</div></code></pre>
<h2 id="常用注解">常用注解</h2>
<p>@PathVariable(&quot;id&quot;)配合@RequestMapping(&quot;url/{id}&quot;)使用:</p>
<p><img src="file:///e:\notepad\notepad\springboot\spring%E5%9F%BA%E7%A1%80\assets\image-20201121193727636.png" alt="image-20201121193727636"></p>
<pre><code class="language-java"><div><span class="hljs-meta">@MapperScan</span>(basePackages = {<span class="hljs-string">"cn.viwiv.inter.mapper"</span>}) <span class="hljs-comment">// 扫描Mapper生成bean</span>
<span class="hljs-meta">@Value</span>(<span class="hljs-string">"${xxx.xxx}"</span>)<span class="hljs-comment">//注入值</span>
<span class="hljs-comment">// 针对不同的配置加载不同的类</span>
<span class="hljs-meta">@Conditional</span> <span class="hljs-comment">//这类注解用于条件注入</span>
<span class="hljs-meta">@ConditionalOnProperty</span>(prefix = <span class="hljs-string">"run.email"</span>, value = <span class="hljs-string">"enableed"</span>, matchIfMissing = <span class="hljs-keyword">true</span>)<span class="hljs-comment">// 使用注解控制是否生效， matchIfMissing如果不配置是否注入当前类</span>
<span class="hljs-meta">@ConditionalOnBean</span>(xxx.class) <span class="hljs-comment">// 指定的xxx.class的bean存在时，注入当前bean</span>
<span class="hljs-meta">@ConditionalOnMissingBean</span>(xxx.class) <span class="hljs-comment">// 如果没有xxx.class的bean就注入</span>
</div></code></pre>
<pre><code class="language-java"><div><span class="hljs-meta">@Configuration</span>
<span class="hljs-meta">@ConditionalOnMissingBean</span>(cn.viwiv.impl.service.EmailService.class)
<span class="hljs-meta">@ConditionalOnProperty</span>(value = <span class="hljs-string">"dev.email.emailService"</span>)
<span class="hljs-meta">@Service</span>
<span class="hljs-keyword">public</span> <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">EmailService</span> <span class="hljs-keyword">implements</span> <span class="hljs-title">IEmailService</span> </span>{}
</div></code></pre>
<pre><code class="language-java"><div><span class="hljs-comment">//自动注销bean</span>
<span class="hljs-meta">@Configuration</span>
<span class="hljs-keyword">public</span> <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">UserServiceMockConfig</span> <span class="hljs-keyword">implements</span> <span class="hljs-title">BeanDefinitionRegistryPostProcessor</span> </span>{

    <span class="hljs-meta">@Override</span>
    <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title">postProcessBeanDefinitionRegistry</span><span class="hljs-params">(BeanDefinitionRegistry beanDefinitionRegistry)</span> <span class="hljs-keyword">throws</span> BeansException </span>{

    }

    <span class="hljs-meta">@Override</span>
    <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title">postProcessBeanFactory</span><span class="hljs-params">(ConfigurableListableBeanFactory factory)</span>
            <span class="hljs-keyword">throws</span> BeansException </span>{
        <span class="hljs-comment">// 先删除容器中的Bean定义</span>
        ((DefaultListableBeanFactory) factory).removeBeanDefinition(<span class="hljs-string">"userService"</span>);

        <span class="hljs-comment">// 创建mock的Bean，并注册到Spring容器</span>
        BeanDefinitionBuilder builder = BeanDefinitionBuilder.genericBeanDefinition(IUserService.class, () -&gt; uname -&gt; {
            Random random = <span class="hljs-keyword">new</span> Random();
            <span class="hljs-keyword">return</span> random.nextInt(<span class="hljs-number">1024</span>);
        });

        BeanDefinition beanDefinition = builder.getRawBeanDefinition();
        ((DefaultListableBeanFactory) factory).registerBeanDefinition(<span class="hljs-string">"userService"</span>, beanDefinition);
    }
}
</div></code></pre>

    </body>
    </html>